/**
 * @author haixuanwo
 * @email haixuanwo_clark@hotmail.com
 * @date 2021-03-25
 * @brief 学生管理
 */

#include <iostream>
#include "studentManager.h"

#define CREATE_STUDENT_TABLE "CREATE TABLE STUDENT(" \
                          "NAME        TEXT     NOT NULL," \
                          "AGE         INT      NOT NULL," \
                          "STUDENTID   INT      NOT NULL," \
                          "GENDER      INT      NOT NULL,"  \
                          "SCORE       INT      NOT NULL);"

#define SELECT_ALL_STUDENT "SELECT * from STUDENT"

#define SELECT_STUDENT_TABLE "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='STUDENT';"

StudentManager::StudentManager()
{
    v_student = new std::vector<Student_t>;
    studentDB = new mySqlite(STUDENT_MANAGE_SYSTEM);

    int tableCount = 0;
    if (studentDB->exec_sql_cmd(SELECT_STUDENT_TABLE, &tableCount))
    {
        if (0 < tableCount)
        {
            // 获取数据库中用户数据
            get_all_student();
            show_all_student();
        }
        else
        {
            // 创建用户表
            if(studentDB->exec_sql_cmd(CREATE_STUDENT_TABLE))
                std::cout<<"create table user successful"<<std::endl;
            else
                std::cout<<"create table user fail"<<std::endl;
        }
    }
}

bool StudentManager::add_student(Student_t &NewStudent)
{
    if (match_student(NewStudent.studentID))
    {
        std::cout<<"the student already exist, add fail"<<std::endl;
        return false;
    }

    std::cout<<"1================"<<std::endl;

    v_student->push_back(NewStudent);

    std::cout<<"2================"<<std::endl;

    char cmd[1024] = {0};
    snprintf(cmd, sizeof(cmd),
        "INSERT INTO STUDENT (NAME,AGE,STUDENTID,GENDER,SCORE) VALUES ('%s', %d, %d, %d, %d);",
        NewStudent.name.c_str(), NewStudent.age, NewStudent.studentID, NewStudent.gender, NewStudent.score);

    std::cout<<"3================"<<std::endl;
    if (studentDB->exec_sql_cmd(cmd))
    {
        std::cout<<"add user successful!"<<std::endl;
        std::cout<<"name:"<<NewStudent.name<<" age:"<<NewStudent.age<<" studentID:"<<NewStudent.studentID \
            <<" gender:"<<NewStudent.gender<<" score:"<<NewStudent.score<<std::endl;
        show_all_student();
        return true;
    }
    else
        std::cout<<"add user fail"<<std::endl;

    std::cout<<"4================"<<std::endl;
    return false;
}


bool StudentManager::delete_student(int studentID)
{
    char sqlCmd[1024] = {0};

    for (auto it = v_student->begin(); it != v_student->end(); ++it)
    {
        if (studentID == it->studentID)
        {
            snprintf(sqlCmd, sizeof(sqlCmd),  "DELETE from STUDENT where STUDENTID=%d;", studentID);
            if (studentDB->exec_sql_cmd(sqlCmd))
            {
                std::cout<<"delete student successful!"<<std::endl;
                std::cout<<"name:"<<it->name<<" age:"<<it->age<<" studentID:"<<it->studentID \
                        <<" gender:"<<it->gender<<" score:"<<it->score<<std::endl;
                v_student->erase(it);
                show_all_student();
                return true;
            }

            std::cout<<"delete student fail"<<std::endl;
        }
    }
    return false;
}

bool StudentManager::select_student(int studentID)
{
    Student_t student;
    if (match_student(studentID, &student))
    {
        std::cout<<"select student successful"<<std::endl;
        std::cout<<"name:"<<student.name<<" age:"<<student.age<<" studentID:"<<student.studentID \
                        <<" gender:"<<student.gender<<" score:"<<student.score<<std::endl;
        return true;
    }
    else
    {
        std::cout<<"select fail haven't student ID:"<<studentID<<std::endl;
        return false;
    }
}

bool StudentManager::change_student(Student_t &student)
{
    char sqlCmd[1024] = {0};

    for (auto it = v_student->begin(); it != v_student->end(); ++it)
    {
        if (it->studentID == student.studentID)
        {
            snprintf(sqlCmd, sizeof(sqlCmd),
                "UPDATE STUDENT set NAME='%s', AGE=%d, GENDER=%d, SCORE=%d where STUDENTID=%d;",
                    student.name.c_str(), student.age, student.gender, student.score, student.studentID);

            if (studentDB->exec_sql_cmd(sqlCmd))
            {
                std::cout<<"update user successful!"<<std::endl;

                std::cout<<"old student name:"<<it->name<<" age:"<<it->age<<" studentID:"<<it->studentID \
                        <<" gender:"<<it->gender<<" score:"<<it->score<<std::endl;

                std::cout<<"new student name:"<<student.name<<" age:"<<student.age<<" studentID:"<<student.studentID \
                        <<" gender:"<<student.gender<<" score:"<<student.score<<std::endl;

                it->name = student.name;
                it->age  = student.age;
                it->gender  = student.gender;
                it->score  = student.score;
                show_all_student();
                return true;
            }
        }
    }

    std::cout<<"change student fail"<<std::endl;
    return false;
}

bool StudentManager::match_student(int studentID, Student_t *matchedStudent)
{
    for (auto student:*v_student)
    {
        // 匹配name
        if (studentID == student.studentID)
        {
            /*
            // 匹配passwd
            if (nullptr != passwd && 0 != student.passwd.compare(*passwd))
            {
                continue;
            }*/

            // 获取匹配的学生
            if (nullptr != matchedStudent)
            {
                *matchedStudent = student;
            }
            return true;
        }
    }
    return false;
}

// 从数据库中获取所有学生数据
bool StudentManager::get_all_student()
{
    std::string tableData;

    if (studentDB->sql_select(SELECT_ALL_STUDENT, tableData))
    {
        // 初始化v_user容器
        Student_t student;
        auto pos = 0;

        pos = tableData.find_first_of(';');
        tableData.erase(0, pos+1);  // 删除第一行的元素名称

        while (tableData.size())
        {
            pos = tableData.find_first_of(',');
            student.name = tableData.substr(0, pos);
            tableData.erase(0, pos+1);

            pos = tableData.find_first_of(',');
            student.age = atoi(tableData.substr(0, pos).c_str());
            tableData.erase(0, pos+1);

            pos = tableData.find_first_of(',');
            student.studentID = atoi(tableData.substr(0, pos).c_str());
            tableData.erase(0, pos+1);

            pos = tableData.find_first_of(',');
            student.gender = atoi(tableData.substr(0, pos).c_str());
            tableData.erase(0, pos+1);

            pos = tableData.find_first_of(';');
            student.score = atoi(tableData.substr(0, pos).c_str());
            tableData.erase(0, pos+1);

            v_student->push_back(student);
        }
        return true;
    }
    return false;
}


void StudentManager::show_all_student()
{
    if (0 < v_student->size())
    {
        std::cout<<"show all student"<<std::endl;
        for (auto student:*v_student)
        {
            std::cout<<"name:"<<student.name<<std::endl;
            std::cout<<"age:"<<student.age<<std::endl;
            std::cout<<"studentID:"<<student.studentID<<std::endl;
            std::cout<<"gender:"<<student.gender<<std::endl;
            std::cout<<"score:"<<student.score<<std::endl;
        }
    }
    else
    {
        std::cout<<"have no student data"<<std::endl;
    }
}


StudentManager::~StudentManager()
{
    delete v_student;
    v_student = nullptr;

    delete studentDB;
    studentDB = nullptr;
}

